package com.micro.platform.oauth.framework.domain;

import com.micro.platform.oauth.framework.constants.OauthConstants;
import com.micro.platform.starter.utils.NumberUtils;
import lombok.Data;
import org.apache.commons.collections4.MapUtils;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.Map;

@Data
public class AccessToken implements Serializable {
    private static final long serialVersionUID = 8841433872811285796L;
    private String accessToken;
    private Long expiresTime;
    private Long expiresTimeStamp;
    private Map<String, Object> data;
    private String refreshToken;
    private Long refreshExpiresTime;
    private String account;
    private String clientId;
    private String[] scopes;
    private String subjectKey;

    public AccessToken() {
    }

    public AccessToken(String accessToken, RefreshToken refreshToken, Map<String, Object> accesstokenData) {
        this.accessToken = accessToken;
        this.data = accesstokenData;
        this.expiresTime = MapUtils.getLong(this.data, OauthConstants.TokenData.KEY_IS_EXPIRES_TIME);
        this.expiresTimeStamp = LocalDateTime.now().plusSeconds(this.expiresTime).atZone(ZoneOffset.of("+8")).toInstant().toEpochMilli();
        if(refreshToken != null){
            this.refreshToken = refreshToken.getRefreshToken();
            this.refreshExpiresTime = refreshToken.getExpiresTime();
        }
        this.account = MapUtils.getString(data,OauthConstants.TokenData.KEY_IS_ACCOUNT);
        this.clientId = MapUtils.getString(data,OauthConstants.TokenData.KEY_IS_CLIENT_ID);
        this.scopes = (String[]) MapUtils.getObject(data,OauthConstants.TokenData.KEY_IS_SCOPES);
        this.subjectKey = MapUtils.getString(data,OauthConstants.TokenData.KEY_IS_SUBJECT_KEY);
    }

    public AccessToken(Map<String, Object> data) {
        this.refreshToken = MapUtils.getString(data,OauthConstants.TokenData.KEY_IS_REFRESH_TOKEN);
        this.accessToken = MapUtils.getString(data,OauthConstants.TokenData.KEY_IS_ACCESS_TOKEN);
        this.expiresTime = MapUtils.getLong(data,OauthConstants.TokenData.KEY_IS_EXPIRES_TIME);
        this.refreshExpiresTime = MapUtils.getLong(data,OauthConstants.TokenData.KEY_IS_REFRESH_EXPIRES_TIME);
        this.expiresTimeStamp = MapUtils.getLong(data,OauthConstants.TokenData.KEY_IS_EXPIRES_TIME_STAMP);
        this.account = MapUtils.getString(data,OauthConstants.TokenData.KEY_IS_ACCOUNT);
        this.clientId = MapUtils.getString(data,OauthConstants.TokenData.KEY_IS_CLIENT_ID);
        this.scopes = (String[]) MapUtils.getObject(data,OauthConstants.TokenData.KEY_IS_SCOPES);
        this.subjectKey = MapUtils.getString(data,OauthConstants.TokenData.KEY_IS_SUBJECT_KEY);
        this.data = data;
    }

    public Map<String, Object> toMap(){
        if(data == null){
            data = new HashMap<>();
        }
        data.put(OauthConstants.TokenData.KEY_IS_REFRESH_TOKEN, refreshToken);
        data.put(OauthConstants.TokenData.KEY_IS_ACCESS_TOKEN, accessToken);
        data.put(OauthConstants.TokenData.KEY_IS_EXPIRES_TIME, expiresTime);
        data.put(OauthConstants.TokenData.KEY_IS_REFRESH_EXPIRES_TIME, refreshExpiresTime);
        data.put(OauthConstants.TokenData.KEY_IS_EXPIRES_TIME_STAMP, expiresTimeStamp);
        data.put(OauthConstants.TokenData.KEY_IS_SUBJECT_KEY, subjectKey);
        return data;
    }

    public boolean unExpires(){
        if(this.expiresTimeStamp == null){
            return true;
        }
        return NumberUtils.compare(this.expiresTimeStamp, LocalDateTime.now().atZone(ZoneOffset.of("+8")).toInstant().toEpochMilli()) > 0;
    }
}
